package yagwl.service.demo;

import java.util.List;
import java.util.logging.Logger;

import javax.persistence.EntityManager;

import yagwl.service.util.db.DaoContext;
import yagwl.service.util.svc.BaseException;
import yagwl.service.util.svc.BaseException.ErrorCode;

public class CartDao {

  private static final Logger log = Logger.getLogger(CartDao.class.getName());

  private DaoContext ctx;

  public CartDao(DaoContext ctx) {
    this.ctx = ctx;
  }

  public CartEntity getCart(Long cartId) {
    EntityManager em = ctx.em();
    try {
      CartEntity cart = em.find(CartEntity.class, cartId);
      return cart;
    } catch (Exception e) {
      log.severe(e.toString());
    }
    return null;
  }

  private void print(List<CartEntity> list) {
  }

  public CartEntity createCart(Long productId, int quantity) {
    EntityManager em = ctx.em();
    CartEntity cart;
    try {
      em.getTransaction().begin();
      CartLineEntity cartLine = new CartLineEntity();
      cartLine.setProductId(productId);
      cartLine.setQuantity(quantity);
      em.persist(cartLine);
      em.getTransaction().commit();
      
      em.getTransaction().begin();
      cart = new CartEntity();
      cart.getCartLineIds().add(cartLine.getCartLineId());
      cart.getCartLines().add(cartLine);
      em.persist(cart);
      em.getTransaction().commit();
    } catch (Exception e) {
      log.severe(e.toString());
      em.getTransaction().rollback();
      throw new BaseException(ErrorCode.INTERNAL_TRANSACTION_ERROR, e);
    }
    return cart;
  }

  public CartEntity addToCart(CartEntity cart, Long productId, int quantity) {
    EntityManager em = ctx.em();
    try {
      // if product already exists, update quantity
      for (int i = 0; i < cart.getCartLineIds().size(); i++) {
        CartLineEntity cartLine = cart.getCartLines().get(i);
        if (productId.equals(cartLine.getProductId())) {
          em.getTransaction().begin();
          cartLine.setQuantity(cartLine.getQuantity() + 1);
          em.merge(cartLine);
          em.getTransaction().commit();
          return cart;
        }
      }

      // product doesn't exist; create new line and add to cart
      em.getTransaction().begin();
      CartLineEntity cartLine = new CartLineEntity();
      cartLine.setProductId(productId);
      cartLine.setQuantity(quantity);
      em.persist(cartLine);
      em.getTransaction().commit();

      em.getTransaction().begin();
      cart.getCartLineIds().add(cartLine.getCartLineId());
      cart.getCartLines().add(cartLine);
      em.merge(cart);
      em.getTransaction().commit();
    } catch (Exception e) {
      log.severe(e.toString());
      em.getTransaction().rollback();
      throw new BaseException(ErrorCode.INTERNAL_TRANSACTION_ERROR, e);
    }
    return cart;
  }

  public CartEntity removeFromCart(CartEntity cart, Long productId) {
    EntityManager em = ctx.em();
    try {
      for (int i = 0; i < cart.getCartLineIds().size(); i++) {
        CartLineEntity cartLine = cart.getCartLines().get(i);
        if (productId.equals(cartLine.getProductId())) {
          em.getTransaction().begin();
          CartLineEntity line = cart.getCartLines().remove(i);
          line = null;
          // remove cartLineId in an independent loop, in case 
          // cartLines and cartLineIds are not in same order
          for (int j = 0; j < cart.getCartLineIds().size(); j++) {
            if (cart.getCartLineIds().get(j).equals(cartLine.getCartLineId())) {
              cart.getCartLineIds().remove(j);
              break;
            }
          }
          em.merge(cart);
          em.getTransaction().commit();
          break;
        }
      }
    } catch (Exception e) {
      log.severe(e.toString());
      em.getTransaction().rollback();
      throw new BaseException(ErrorCode.INTERNAL_TRANSACTION_ERROR, e);
    }
    return cart;
  }

}
